from flask import Flask, render_template, request, redirect, url_for, session
import sqlite3
import math
from collections import defaultdict

app = Flask(__name__)
app.config['DATABASE'] = 'movie_recommender.db'
app.secret_key = 'your-secret-key-here'  # 用于session管理

# 连接数据库
def get_db():
    conn = sqlite3.connect(app.config['DATABASE'])
    conn.row_factory = sqlite3.Row
    return conn

# 初始化数据库
def init_db():
    with app.app_context():
        db = get_db()
        
        # 创建电影表
        db.execute('''
            CREATE TABLE IF NOT EXISTS movies (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                title TEXT NOT NULL,
                genre TEXT NOT NULL,
                director TEXT,
                year INTEGER,
                description TEXT
            )
        ''')
        
        # 创建评分表
        db.execute('''
            CREATE TABLE IF NOT EXISTS ratings (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                user_id INTEGER NOT NULL DEFAULT 1,  # 简化版，默认为用户1
                movie_id INTEGER NOT NULL,
                rating INTEGER NOT NULL CHECK (rating BETWEEN 1 AND 5),
                FOREIGN KEY (movie_id) REFERENCES movies (id)
            )
        ''')
        
        # 插入示例电影数据
        sample_movies = [
            ('肖申克的救赎', '剧情', '弗兰克·德拉邦特', 1994, '一个被错误定罪的银行家在监狱中的生活'),
            ('教父', '犯罪', '弗朗西斯·福特·科波拉', 1972, '一个黑手党家族的故事'),
            ('阿甘正传', '剧情', '罗伯特·泽米吉斯', 1994, '一个智商不高的人的非凡人生'),
            ('泰坦尼克号', '爱情', '詹姆斯·卡梅隆', 1997, '豪华客轮沉没时的爱情故事'),
            ('盗梦空间', '科幻', '克里斯托弗·诺兰', 2010, '关于梦境和现实的科幻电影'),
            ('星际穿越', '科幻', '克里斯托弗·诺兰', 2014, '关于太空探索和时间旅行的电影'),
            ('复仇者联盟', '动作', '乔斯·韦登', 2012, '超级英雄团队拯救世界的故事'),
            ('蝙蝠侠：黑暗骑士', '动作', '克里斯托弗·诺兰', 2008, '蝙蝠侠与小丑的对决'),
            ('千与千寻', '动画', '宫崎骏', 2001, '一个女孩在神灵世界的冒险'),
            ('寻梦环游记', '动画', '李·昂克里奇', 2017, '关于家庭、记忆和梦想的动画电影')
        ]
        
        # 检查是否已有数据
        existing_movies = db.execute('SELECT COUNT(*) FROM movies').fetchone()[0]
        if existing_movies == 0:
            db.executemany('INSERT INTO movies (title, genre, director, year, description) VALUES (?, ?, ?, ?, ?)', sample_movies)
        
        db.commit()

# 获取电影推荐（基于简单的协同过滤算法）
def get_recommendations(user_id):
    db = get_db()
    
    # 获取用户评分过的电影和评分
    user_ratings = db.execute('''
        SELECT m.id, m.title, m.genre, r.rating 
        FROM movies m 
        JOIN ratings r ON m.id = r.movie_id 
        WHERE r.user_id = ?
    ''', (user_id,)).fetchall()
    
    # 如果用户没有评分任何电影，返回热门电影
    if not user_ratings:
        return db.execute('SELECT * FROM movies LIMIT 5').fetchall()
    
    # 计算用户对各个类型的平均评分
    genre_ratings = defaultdict(list)
    for movie in user_ratings:
        genre_ratings[movie['genre']].append(movie['rating'])
    
    genre_avg_ratings = {genre: sum(ratings)/len(ratings) for genre, ratings in genre_ratings.items()}
    
    # 获取用户还没有评分的电影
    rated_movie_ids = [movie['id'] for movie in user_ratings]
    unrated_movies = db.execute('SELECT * FROM movies WHERE id NOT IN ({})'.format(','.join('?' for _ in rated_movie_ids)), rated_movie_ids).fetchall()
    
    # 为未评分的电影打分，基于类型匹配度
    scored_movies = []
    for movie in unrated_movies:
        score = 0
        # 如果电影的类型在用户喜欢的类型中，给予更高的分数
        if movie['genre'] in genre_avg_ratings:
            score = genre_avg_ratings[movie['genre']]
        else:
            score = 3  # 默认分数
        scored_movies.append((movie, score))
    
    # 按分数排序，返回前5部电影
    scored_movies.sort(key=lambda x: x[1], reverse=True)
    recommended_movies = [movie for movie, score in scored_movies[:5]]
    
    db.close()
    return recommended_movies

@app.route('/')
def index():
    # 显示热门电影
    db = get_db()
    popular_movies = db.execute('SELECT * FROM movies LIMIT 10').fetchall()
    db.close()
    return render_template('index.html', movies=popular_movies)

@app.route('/movies')
def movies():
    # 显示所有电影
    db = get_db()
    all_movies = db.execute('SELECT * FROM movies').fetchall()
    db.close()
    return render_template('movies.html', movies=all_movies)

@app.route('/movie/<int:movie_id>')
def movie_detail(movie_id):
    # 显示电影详情
    db = get_db()
    movie = db.execute('SELECT * FROM movies WHERE id = ?', (movie_id,)).fetchone()
    
    # 获取电影的平均评分
    avg_rating = db.execute('''
        SELECT AVG(rating) as avg FROM ratings WHERE movie_id = ?
    ''', (movie_id,)).fetchone()['avg']
    
    # 获取用户对该电影的评分
    user_rating = db.execute('''
        SELECT rating FROM ratings WHERE movie_id = ? AND user_id = ?
    ''', (movie_id, 1)).fetchone()
    
    db.close()
    
    if avg_rating is None:
        avg_rating = 0
    else:
        avg_rating = round(avg_rating, 1)
    
    return render_template('movie_detail.html', movie=movie, avg_rating=avg_rating, user_rating=user_rating)

@app.route('/rate_movie', methods=['POST'])
def rate_movie():
    movie_id = request.form['movie_id']
    rating = request.form['rating']
    user_id = 1  # 简化版，默认为用户1
    
    db = get_db()
    
    # 检查用户是否已经评分过这部电影
    existing_rating = db.execute('''
        SELECT id FROM ratings WHERE movie_id = ? AND user_id = ?
    ''', (movie_id, user_id)).fetchone()
    
    if existing_rating:
        # 更新评分
        db.execute('''
            UPDATE ratings SET rating = ? WHERE id = ?
        ''', (rating, existing_rating['id']))
    else:
        # 添加新评分
        db.execute('''
            INSERT INTO ratings (user_id, movie_id, rating) VALUES (?, ?, ?)
        ''', (user_id, movie_id, rating))
    
    db.commit()
    db.close()
    
    return redirect(url_for('movie_detail', movie_id=movie_id))

@app.route('/recommendations')
def recommendations():
    # 获取推荐电影
    user_id = 1  # 简化版，默认为用户1
    recommended_movies = get_recommendations(user_id)
    
    return render_template('recommendations.html', movies=recommended_movies)

@app.route('/search', methods=['POST'])
def search():
    # 搜索电影
    query = request.form['query']
    db = get_db()
    
    # 在标题、类型和导演中搜索
    search_results = db.execute('''
        SELECT * FROM movies 
        WHERE title LIKE ? OR genre LIKE ? OR director LIKE ?
    ''', (f'%{query}%', f'%{query}%', f'%{query}%')).fetchall()
    
    db.close()
    
    return render_template('movies.html', movies=search_results, search_query=query)

if __name__ == '__main__':
    # 初始化数据库
    init_db()
    # 运行应用
    app.run(debug=True)